home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_351 / pdc / pdcsrc.lzh / A68k / Codegen.c < prev    next >
C/C++ Source or Header  |  1990-04-19  |  27KB  |  894 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*            MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*        Copyright (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*              Object code generator - November 1, 1989        */
  8. /*                                    */
  9. /*   This program may be copied for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on all copies of the source code.  Copying for any other use   */
  12. /*   without the consent of the author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr. Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*     AmigaDOS conversion copyright 1989 by Charlie Gibbs.        */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "A68kdef.h"
  25. #include "A68kglb.h"
  26.  
  27. /* Functions */
  28. extern int  LineParts(), Instructions(), ObjDir();
  29. extern int  GetInstModeSize(), GetMultReg(), CountNest();
  30. extern int  ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
  31. extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue();
  32. extern char *AddName(), *GetField();
  33. extern struct SymTab *NextSym();
  34. extern struct SymTab **HashIt();
  35.  
  36.  
  37.  
  38. GetObjectCode (dummy) int dummy;
  39. /* Determines the object code for the operation as well as the operands */
  40. /* Returns each (up to 3 fields), along with the length of each.     */
  41. {
  42.     int  quick;
  43.     int  ExtL;        /* Bit pattern for instruction extension word */
  44.     long templong;
  45.     char tempop[MAXLINE];
  46.     register int i, j;
  47.  
  48.     i = Instructions (OpLoc);        /* Analyze the opcode. */
  49.  
  50.     if (Dir != None) {
  51.     ObjDir (dummy);            /* Process directives. */
  52.     return;
  53.     }
  54.     if ((Label[0] != '\0') || (OpCode[0] != '\0'))
  55.     PrntAddr = TRUE;        /* Print address, at least. */
  56.  
  57.     if (OpCode[0] == '\0') {
  58.     MakeHunk |= PrntAddr;
  59.     return;                /* No opcode, exit now. */
  60.     }
  61.     if (!i) {                /* Unrecognized opcode */
  62.     if ((Quiet < 0) && (InF->UPtr == 0))
  63.         ShowLine (InF->Line);    /* Show where we are. */
  64.     if (OpCode[0] == '*') {
  65.         Error (OpLoc, NoCode);    /* Don't try to open the console! */
  66.         return;
  67.     }
  68.     if (Size == Byte)        /* Set up \0 parameter. */
  69.         MacSize[0] = 'B';
  70.     else if (Size == Long)
  71.         MacSize[0] = 'L';
  72.     else
  73.         MacSize[0] = 'W';
  74.  
  75.     AddrAdv = InstSize = 0;
  76.     PrntAddr = FALSE;
  77.     Dir = MacCall;            /* Assume it's a macro call. */
  78.     if (InF->UPtr == 0) {        /* If we're reading from a file */
  79.         InF->Pos = lseek (In.fd, 0L,1); /*  remember where we are.  */
  80.         InF->Pos -= In.Lim - In.Ptr;
  81.     }
  82.     tempop[0] = ' ';
  83.     tempop[1] = '\0';
  84.     strcat (tempop, OpCode);    /* Prepend a blank to OpCode. */
  85.     if (ReadSymTab (tempop)) {    /* Search for user macro. */
  86.         AddRef (LineCount);
  87.         if(Sym->Defn < LineCount) {    /* Only if previously defined! */
  88.         InFNum++;
  89.         if (--InF < LowInF)
  90.             LowInF = InF;
  91.         MacCount++;
  92.         Heap2Space (0);            /* Check for space. */
  93.         InF->UPtr = (char *) Hunk2;    /* MACRO statement */
  94.         InF->UPtr += strlen(InF->UPtr) + 1; /* Skip over it. */
  95.         InF->NPtr = NextFNS;    /* New stack pointer */
  96.         InF->Line = 0;        /* Line number in macro */
  97.         InF->NArg=GetArgs (""); /* Get arguments. */
  98.         InF->MCnt = MacCount;    /* Macro number */
  99.         if (OuterMac == 0)
  100.             OuterMac = InFNum;    /* Outer macro */
  101.         return;
  102.         }
  103.     }
  104.     if (!OpenIncl (OpCode, InclList)) {
  105.         Error (OpLoc, NoCode);    /* Couldn't open file. */
  106.         Dir = BadMac;        /* Invalid macro */
  107.         if (InF->UPtr == 0) {
  108.         In.fd = open (InF->NPtr, 0);
  109.         lseek (In.fd, InF->Pos, 0);
  110.         In.Ptr = In.Lim = In.Buf;
  111.         }
  112.         return;            /* Return to outer file. */
  113.     }
  114.     InFNum++;            /* Bump nesting level. */
  115.     if (--InF < LowInF)
  116.         LowInF = InF;
  117.     MacCount++;
  118.     Heap2Space (0);            /* Check for space. */
  119.     InF->UPtr = 0;            /* Not a user macro. */
  120.     InF->NPtr = NextFNS;        /* New stack pointer */
  121.     InF->Line = 0;            /* Line number in macro */
  122.     InF->NArg = GetArgs (OpCode);    /* Get arguments. */
  123.     InF->MCnt = MacCount;        /* Macro number */
  124.     if (OuterMac == 0)
  125.         OuterMac = InFNum;        /* Outer macro */
  126.     return;
  127.     }
  128.  
  129.     MakeHunk = TRUE;            /* We have something for a hunk. */
  130.     AddrCnt = AddrBndW (AddrCnt);    /* It'll be word-aligned. */
  131.  
  132.     if ((AdrModeA != 0) || (AdrModeB != 0)) {
  133.     Src.Loc = SrcLoc;
  134.     Dest.Loc = DestLoc;
  135.     if (SrcPC IN AdrModeB)    /* Source operand can be PC-relative. */
  136.         if (EA05z IN AdrModeB)
  137.         i = 4;        /* Displacement offset is 4 for MOVEM. */
  138.         else
  139.         i = 2;        /* Offset is 2 for all others. */
  140.     else
  141.         i = 0;        /* PC-relative modes are not allowed. */
  142.     GetOperand (SrcOp, &Src, i);
  143.     GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0);
  144.     }
  145.     if ((EA05z IN AdrModeB) && !NoOpt) {    /* MOVEM */
  146.     if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) {
  147.         OpCode[4] = '\0';           /* MOVEM of a single register */
  148.         Instructions (OpLoc);    /*  becomes a straight MOVE.  */
  149.     }
  150.     }
  151.     if ((Src.Mode == Imm)        /* Immediate instructions */
  152.     && (Src.Hunk == ABSHUNK) && (Src.Defn < LineCount)
  153.     && !NoOpt
  154.     &&     (((EA611 IN AdrModeB) && (Dest.Mode == DReg)    /* MOVE */
  155.         && (Size == Long) && (Src.Value >= -128) && (Src.Value <= 127))
  156.     || ((EA05y IN AdrModeB)                /* ADD/SUB */
  157.         && (Src.Value > 0) && (Src.Value <= 8)))) {
  158.         strcat (OpCode, "Q");   /* Make it ADDQ/SUBQ/MOVEQ. */
  159.         Instructions (OpLoc);
  160.     }
  161.     else if ((Dest.Mode == ARDir) && (Src.Mode <= 12)
  162.     && (((EA05y | EA611) IN AdrModeB)    /* ADD, SUB, or MOVE */
  163.     || (OpM68C IN AdrModeA))) {    /* CMP */
  164.         strcat (OpCode, "A");       /* ADD op,An becomes ADDA etc. */
  165.         Instructions (OpLoc);
  166.     }
  167.     else if ((Src.Mode == Imm)        /* Immediate instructions */
  168.     && ((OpM68D | OpM68C | OpM68X) IN AdrModeA)) {
  169.     strcat (OpCode, "I");           /* ADD/AND/OR/SUB, CMP, EOR */
  170.     Instructions (OpLoc);        /* ADD #op,d becomes ADDI etc. */
  171.     }
  172.     else if ((Src.Mode == ARPost) && (Dest.Mode == ARPost)
  173.     && (OpM68C IN AdrModeA)) {        /* CMP */
  174.     strcat (OpCode, "M");           /* Generate CMPM if necessary. */
  175.     Instructions (OpLoc);
  176.     }
  177.  
  178.  
  179. /*=================== Operand validation routines ====================*/
  180.  
  181.     if (Pass2) {
  182.  
  183.     /* If an immediate operand isn't absolute, it must be a long word. */
  184.  
  185.     if ((Src.Mode == Imm) && (Size != Long) && (Src.Hunk != ABSHUNK))
  186.         Error (SrcLoc, RelErr);
  187.  
  188.     /* ------- Check for instructions with too many operands. ------- */
  189.     /* Some specialized instruction routines contain their own tests. */
  190.  
  191.     if (AdrModeA == 0) {        /* Should have only one operand. */
  192.         if ((AdrModeB == EA05e) || (AdrModeB == (Size67 | EA05e))) {
  193.         if (Dest.Mode != Null)
  194.             Error (DestLoc, OperErr);
  195. /*        } else if (AdrModeB == 0) { */  /* Should have no operands. */
  196. /*        if (Src.Mode != Null)
  197.             Error (SrcLoc, OperErr);
  198.         if (Dest.Mode != Null)
  199.             Error (DestLoc, OperErr); De-activated for now */
  200.         }
  201.     }
  202.     if ((AdrModeA != 0) || (AdrModeB != 0)) {
  203.         if(Dest.Mode != NULL) { /* We should never find 3 operands. */
  204.         j = DestLoc + strlen (DestOp);
  205.         if ((Line[j] != '\0')
  206.         && (Line[j] != ';')
  207.         && (!isspace (Line[j]))) {
  208.             Error (j, OperErr);
  209.         }
  210.         }
  211.  
  212.     /* ---------------- Check for missing operands. ----------------- */
  213.  
  214.         if (Src.Mode == Null) {
  215.         Error (OpLoc+strlen(OpCode), OperErr);    /* No source */
  216.         } else if (Dest.Mode == Null) {
  217.         if (((ImmMode & AdrModeB) == ImmMode)
  218.         || (TwoOpsA IN AdrModeA)
  219.         || (TwoOpsB IN AdrModeB)) {
  220.             Error (SrcLoc+strlen(SrcOp), OperErr);  /* No dest. */
  221.         }
  222.         }
  223.     }
  224.     }
  225.  
  226. /*====================================================================*/
  227.  
  228.     /* ---------------- Decrement and Branch (DBcc) ----------------- */
  229.  
  230.     if (DecBr IN AdrModeA) {
  231.     if (Pass2) {
  232.         if (Src.Mode != DReg)
  233.         Error (SrcLoc, ModeErr);
  234.         if (Dest.Value & 1)
  235.         Error (DestLoc, AlignErr);  /* Boundary alignment error */
  236.  
  237.         if (Dest.Hunk == CurrHunk) {
  238.         ObjSrc = Dest.Value-AddrCnt-2;    /* Relative branch distance */
  239.         Dest.Hunk = ABSHUNK;        /* Displacement is absolute */
  240.         } else
  241.         ObjSrc = Dest.Value;    /* Let the linker worry about it. */
  242.  
  243.         if ((ObjSrc > 32767) || (ObjSrc < -32768))
  244.         Error (DestLoc,BraErr);    /* Too far to branch */
  245.  
  246.         if (Dest.Hunk!=CurrHunk) {    /* DBcc to another section */
  247.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  248.         PutRel (templong, Dest.Hunk, 2);
  249.         }
  250.         ObjOp = Op | Src.Rn;
  251.     }
  252.     AddrAdv = 4;
  253.     nO = nS = 2;
  254.     return;
  255.     }
  256.  
  257.     /* ------------ Branch (Bcc, including BRA and BSR) ------------- */
  258.  
  259.     if (Brnch IN AdrModeA) {
  260.     if (Src.Value & 1)
  261.         Error (SrcLoc, AlignErr);    /* Boundary alignment error */
  262.  
  263.     if (!Pass2 && !NoOpt && (Size != Byte)) {
  264.         if ((Src.Defn < LineCount)    /* Backward branch */
  265.         && (Src.Hunk == CurrHunk)) {
  266.         ObjSrc = Src.Value-AddrCnt-2;    /* Relative branch distance */
  267.         Src.Hunk = ABSHUNK;        /* Displacement is absolute. */
  268.         if ((ObjSrc != 0) && (ObjSrc >= -128) && (ObjSrc <= 127)) {
  269.             Size = Byte;    /* Convert to a short branch. */
  270.             if ((char *) FwdLim2 >= ((char *) FwdCurr + FWDSIZE)) {
  271.             FwdCurr->Link =    /* Get a new chunk. */
  272.                 (struct FwdTable *) malloc ((unsigned) FWDSIZE);
  273.             if (FwdCurr->Link == NULL)
  274.                 quit_cleanup ("Out of memory!\n");
  275.             FwdCurr = FwdCurr->Link;
  276.             FwdCurr->Link = NULL;
  277.             FwdLim2 = (int *)
  278.                 ((char *) FwdCurr + sizeof (struct FwdTable *));
  279.             }
  280.             *FwdLim2++ = LineCount;    /* Flag branch in pass 2. */
  281.         }
  282.         } else if (Src.Single && (Src.Defn == NODEF)) {    /* Forward */
  283.         if (!ReadSymTab (SrcOp))     /* Store candidate target. */
  284.             AddSymTab (SrcOp, 0L, (long)ABSHUNK, NODEF, 0);
  285.         PackFwdBranch (dummy);    /* Drop expired entries. */
  286.         FwdLim1->Loc = AddrCnt;    /* Location of candidate */
  287.         FwdLim1->FwdSym = Sym;    /* Symbol table entry for target */
  288.         FwdLim1->Line = LineCount;    /* Line number */
  289.         FwdLim1++;
  290.         }
  291.     }
  292.  
  293.     if (Pass2 && !NoOpt && (Size != Byte)) {    /* Pass 2 */
  294.         FwdCurr = FwdStart;    /* Scan the entire foward branch table. */
  295.         FwdPtr = (int *) ((char *) FwdCurr + sizeof (struct FwdTable *));
  296.         while (FwdPtr != FwdLim2) {
  297.         if (*FwdPtr == LineCount) {    /* We flagged it in pass 1. */
  298.             Size = Byte;    /* Make it a short branch */
  299.             break;
  300.         } else {
  301.             FwdPtr++;        /* Scan forward in table. */
  302.             if (FwdPtr == FwdLim2)
  303.             break;
  304.             if ((char *) FwdPtr >= ((char *) FwdCurr + FWDSIZE)) {
  305.             FwdCurr = FwdCurr->Link;    /* Next chunk */
  306.             FwdPtr = (int *)
  307.                 ((char *) FwdCurr + sizeof (struct FwdTable *));
  308.             }
  309.         }
  310.         }
  311.     }
  312.     if (Src.Hunk == CurrHunk) {
  313.         ObjSrc=Src.Value-AddrCnt-2;    /* Relative branch distance */
  314.         Src.Hunk = ABSHUNK;        /* Displacement is absolute. */
  315.         if ((Size == Byte) && (ObjSrc == 0))
  316.         Error (SrcLoc, BccSDsp0);    /* Can't do this! */
  317.         if (Pass2 && FwdProc && (Size != Byte) 
  318.         && (ObjSrc >= -128) && (ObjSrc <= 129) && (ObjSrc != 2))
  319.         FwdShort=TRUE;    /* Forward reference could be made short. */
  320.     } else {
  321.         ObjSrc = Src.Value;        /* Let the linker worry about it. */
  322.         if (Size == Byte)
  323.         Error (SrcLoc, BraErr);    /* No external short branches! */
  324.     }
  325.  
  326.     if (Size != Byte) {
  327.         InstSize = 4;
  328.         nS = 2;
  329.         templong = 32767;
  330.     } else {
  331.         InstSize = 2;
  332.         Op |= (ObjSrc & 0x00FF);
  333.         templong = 127;
  334.     }
  335.     if ((ObjSrc > templong) || (ObjSrc < -templong-1))
  336.         Error (SrcLoc, BraErr);    /* Too far to branch */
  337.  
  338.     if (Dest.Mode != Null)
  339.         Error (DestLoc, OperErr);    /* No Destination operand! */
  340.  
  341.     AddrAdv = InstSize;
  342.     ObjOp = Op;
  343.     nO = 2;
  344.     if (Src.Hunk != CurrHunk) {    /* Bcc to another section */
  345.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  346.         PutRel (templong, Src.Hunk, 2);
  347.     }
  348.     return;
  349.     }
  350.  
  351.     /* --------------- JSR.S and BSR.S are not valid! --------------- */
  352.  
  353.     if (((Op == JMP) || (Op == JSR)) && (Size == Byte))
  354.     Error (OpLoc + 4, SizeErr);
  355.  
  356. /*  Uses information from Instructions & GetOperand (among others)  */
  357. /*  to complete calculation of Object Code.                         */
  358. /*  Op, AdrModeA, AdrModeB, Size, and Src & Dest records are all    */
  359. /*  Global variables imported from the SyntaxAnalyzer MODULE.       */
  360.  
  361.     ExtL = 0;
  362.     quick = FALSE;
  363.  
  364.     /* Ignore size specification on BCHG, BCLR, BSET, and BTST. */
  365.  
  366.     if (Bit811 IN AdrModeB)
  367.     Size = Word;
  368.  
  369.     /* ------------ Check for boundary alignment errors. ------------ */
  370.     /*  BCHG, BCLR, BSET, BTST, LEA, NBCD, PEA, Scc, TAS are exempt.  */
  371.  
  372.     if (Pass2) {
  373.     if ((Size != Byte)
  374.     && (Op != LEA)
  375.     && (Op != PEA)
  376.     && !((AdrModeA == 0) && (AdrModeB == 0))
  377.     && !(AdrModeB & EA05c)        /* BTST */
  378.     && !((AdrModeB&EA05e) && (AdrModeA==0) && !(AdrModeB&Size67))) {
  379.         if (Src.Value & 1)
  380.         if ((Src.Mode >= ARDisp) && (Src.Mode <= PCDisX))
  381.             Error (SrcLoc, AlignErr);
  382.         if (Dest.Value & 1)
  383.         if ((Dest.Mode >= ARDisp) && (Dest.Mode <= PCDisX))
  384.             Error (DestLoc, AlignErr);
  385.     }
  386.  
  387. /* Check for special cases first */
  388.  
  389.     if (Op == STOP) {
  390.         if (Src.Mode != Imm)
  391.         Error (SrcLoc, ModeErr);
  392.         if (Dest.Mode != Null)
  393.         Error (DestLoc, OperErr);
  394.     }
  395.  
  396.     if (Op == LINK) {
  397.         Op |= Src.Rn;
  398.         if (Src.Mode != ARDir)
  399.         Error (SrcLoc, ModeErr);
  400.         if (Dest.Mode != Imm)
  401.         Error (DestLoc, ModeErr);
  402.         else if (Dest.Value & 1)
  403.         Error (DestLoc, AlignErr);  /* Boundary alignment error */
  404.     }
  405.  
  406.     if (Op == SWAP) {
  407.         if (!(EA05f IN AdrModeB)) {    /* Ignore if PEA instruction. */
  408.         Op |= Src.Rn;
  409.         if (Src.Mode != DReg)
  410.             Error (SrcLoc, ModeErr);
  411.         if (Dest.Mode != Null)
  412.             Error (DestLoc, OperErr);
  413.         }
  414.     }
  415.  
  416.     if (Op == UNLK) {
  417.         Op |= Src.Rn;
  418.         if (Src.Mode != ARDir)
  419.         Error (SrcLoc, ModeErr);
  420.         if (Dest.Mode != Null)
  421.         Error (DestLoc, OperErr);
  422.     }
  423.  
  424. /* Now do generalized address modes */
  425.  
  426.     if ((Ry02 IN AdrModeA)&&(Rx911 IN AdrModeA)) {    /* Two registers */
  427.         if (Op == CMPM) {        /* Special routine for CMPM */
  428.         Op |= Src.Rn | (Dest.Rn << 9);
  429.         if (Src.Mode != ARPost)
  430.             Error (SrcLoc, ModeErr);
  431.         if (Dest.Mode != ARPost)
  432.             Error (DestLoc, ModeErr);
  433.         } else {        /* Other two-register instructions */
  434.         Op |= Src.Rn | (Dest.Rn << 9);
  435.         if (RegMem3 IN AdrModeA) {
  436.             if (Src.Mode == DReg) {
  437.             if (Dest.Mode != DReg)
  438.                 Error (DestLoc, ModeErr);
  439.             } else if (Src.Mode == ARPre) {
  440.             Op |= 0x0008;
  441.             if (Dest.Mode != ARPre)
  442.                 Error (DestLoc, ModeErr);
  443.             } else
  444.             Error (SrcLoc, OperErr);
  445.         } else {
  446.             if (Src.Mode == ARPost)
  447.             if (Dest.Mode != ARPost)
  448.                 Error (DestLoc, ModeErr);
  449.             else
  450.                 Error (SrcLoc, OperErr);
  451.         }
  452.         }
  453.     }
  454.     }
  455.     if (Data911 IN AdrModeA) {        /* Data in 9-11 (ADDQ/SUBQ) */
  456.     quick = TRUE;
  457.     if (Src.Mode == Imm)
  458.         if ((Src.Value > 0) && (Src.Value <= 8)) {
  459.         if (Src.Value < 8)    /* Data of 8 is coded as 000. */
  460.             Op |= Src.Value << 9;
  461.         } else
  462.         Error (SrcLoc, SizeErr);
  463.     else
  464.         Error (SrcLoc, ModeErr);
  465.     }
  466.  
  467.     if (CntR911 IN AdrModeA) {        /* Only Shift and Rotate use this. */
  468.     if (Dest.Mode == DReg) {
  469.         Op = (Op & 0xF9FF) | Dest.Rn;
  470.         if (Size == Word) Op |= 0x0040;
  471.         if (Size == Long) Op |= 0x0080;
  472.         if (Src.Mode == DReg)
  473.         Op |= 0x0020 | (Src.Rn << 9);
  474.         else if (Src.Mode == Imm) {
  475.         quick = TRUE;
  476.         if ((Src.Value > 0) && (Src.Value <= 8)) { /* Range check */
  477.             if (Src.Value < 8)    /* Data of 8 is coded as 000. */
  478.             Op |= (Src.Value << 9);
  479.         } else
  480.             Error (SrcLoc, SizeErr);
  481.         } else
  482.         Error (SrcLoc, OperErr);
  483.     } else if (Dest.Mode == Null) {
  484.         Op = (Op & 0xFFE7) | 0x00C0;
  485.         EffAdr (&Src, (mea | aea));
  486.     } else
  487.         Error (SrcLoc, ModeErr);
  488.     }
  489.  
  490.     if (Data03 IN AdrModeA) {        /* TRAP Vector in 0-3 */
  491.     quick = TRUE;
  492.     if (Src.Mode == Imm)
  493.         if ((Src.Value >= 0) && (Src.Value < 16))
  494.         Op |= Src.Value;
  495.         else
  496.         Error (SrcLoc, SizeErr);
  497.     else
  498.         Error (SrcLoc, ModeErr);
  499.  
  500.     if (Dest.Mode != Null)
  501.         Error (DestLoc, OperErr);
  502.     }
  503.  
  504.     if (Data07 IN AdrModeA) {        /* Data in 0-7 (MOVEQ) */
  505.     quick = TRUE;
  506.     Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9);
  507.     if (Src.Mode != Imm)
  508.         Error (SrcLoc, ModeErr);
  509.     else if (Dest.Mode != DReg)
  510.         Error (DestLoc, ModeErr);
  511.     else if ((Src.Value < -128) || (Src.Value > 127))
  512.         Error (SrcLoc, SizeErr);
  513.     }
  514.  
  515.     if (Pass2) {
  516.     if (OpM68D IN AdrModeA) {    /* DReg in 6-8 (ADD/AND/OR/SUB) */
  517.         if (Dest.Mode == DReg) {
  518.         Op |= (Dest.Rn << 9);
  519.         if ((Src.Mode == ARDir) && (Size == Byte))
  520.             Error (SrcLoc, SizeErr);
  521.         } else /* Assume Src.Mode = DReg -- errors are trapped elsewhere. */
  522.         Op |= (Src.Rn << 9) | 0x0100;
  523.  
  524.         if (Size == Word) Op |= 0x0040;
  525.         if (Size == Long) Op |= 0x0080;
  526.     }
  527.  
  528.     if (OpM68A IN AdrModeA) {    /* AReg in 6-8 (ADDA/CMPA/SUBA) */
  529.         if (Dest.Mode == ARDir)
  530.         Op |= (Dest.Rn << 9);
  531.         else
  532.         Error (DestLoc, ModeErr);
  533.  
  534.         if (Size == Byte) Error (OpLoc+5, SizeErr);
  535.         if (Size == Word) Op |= 0x00C0;
  536.         if (Size == Long) Op |= 0x01C0;
  537.     }
  538.  
  539.     if (OpM68C IN AdrModeA) {    /* CMP (Compare) */
  540.         if (Dest.Mode == DReg)
  541.         Op |= (Dest.Rn << 9);
  542.         else
  543.         Error (DestLoc, ModeErr);
  544.  
  545.         if (Size == Byte) {
  546.         if (Src.Mode == ARDir)
  547.             Error (OpLoc+4, SizeErr);
  548.         }
  549.         if (Size == Word) Op |= 0x0040;
  550.         if (Size == Long) Op |= 0x0080;
  551.     }
  552.  
  553.     if (OpM68X IN AdrModeA) {    /* EOR (Exclusive or) */
  554.         if (Src.Mode == DReg)
  555.         Op |= (Src.Rn << 9);
  556.         else
  557.         Error (SrcLoc, ModeErr);
  558.  
  559.         if (Size == Byte) Op |= 0x0100;
  560.         if (Size == Word) Op |= 0x0140;
  561.         if (Size == Long) Op |= 0x0180;
  562.     }
  563.  
  564.     if (OpM68S IN AdrModeA) {    /* EXT (Sign extension) */
  565.         if (Src.Mode == DReg)
  566.         Op |= Src.Rn;
  567.         else
  568.         Error (SrcLoc, ModeErr);
  569.  
  570.         if (Dest.Mode != Null)
  571.         Error (DestLoc, OperErr);
  572.  
  573.         if (Size == Byte) Error (OpLoc+4, SizeErr);
  574.         if (Size == Word) Op |= 0x0080;
  575.         if (Size == Long) Op |= 0x00C0;
  576.     }
  577.  
  578.     if (OpM68R IN AdrModeA) {    /* MOVEP (Register/memory) */
  579.         if ((Src.Mode == DReg) && (Dest.Mode == ARDisp)) {
  580.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  581.         if (Size == Word) Op |= 0x0180;
  582.         if (Size == Long) Op |= 0x01C0;
  583.         Op |= (Src.Rn << 9) | Dest.Rn;
  584.         } else if ((Src.Mode == ARDisp) && (Dest.Mode == DReg)) {
  585.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  586.         if (Size == Word) Op |= 0x0100;
  587.         if (Size == Long) Op |= 0x0140;
  588.         Op |= Src.Rn | (Dest.Rn << 9);
  589.         } else
  590.         Error (SrcLoc, ModeErr);
  591.     }
  592.  
  593.     if (OpM37 IN AdrModeA) {    /* EXG (Exchange registers) */
  594.         if ((Src.Mode == DReg) && (Dest.Mode == DReg))
  595.         Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn;
  596.         else if ((Src.Mode == ARDir) && (Dest.Mode == ARDir))
  597.         Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn;
  598.         else if ((Src.Mode == ARDir) && (Dest.Mode == DReg))
  599.         Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn;
  600.         else if ((Src.Mode == DReg) && (Dest.Mode == ARDir))
  601.         Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn;
  602.         else
  603.         Error (SrcLoc, ModeErr);
  604.     }
  605.  
  606.     if (Bit811 IN AdrModeB) {    /* Bit operations using bits 8-11 */
  607.         if (Src.Mode == DReg)
  608.         Op |= 0x0100 | (Src.Rn << 9);
  609.         else if (Src.Mode == Imm)
  610.         Op |= 0x0800;
  611.         else
  612.         Error (SrcLoc, ModeErr);
  613.     }
  614.  
  615.     if (Size67 IN AdrModeB) {    /* Size in bits 6-7 */
  616.      /* if (Size == Byte) ; No action -- bits are already zero. */
  617.         if (Size == Word) Op |= 0x0040;
  618.         if (Size == Long) Op |= 0x0080;
  619.     }
  620.  
  621.     if (Size6 IN AdrModeB) {    /* Size in bit 6 (MOVEM) */
  622.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  623.      /* if (Size == Word) ; No action -- bit is already zero. */
  624.         if (Size == Long) Op |= 0x0040;
  625.     }
  626.  
  627.     if (Sz1213A IN AdrModeB) {    /* Size in 12-13 (MOVE) */
  628.         if (Size == Byte) Op |= 0x1000;
  629.         if (Size == Word) Op |= 0x3000;
  630.         if (Size == Long) Op |= 0x2000;
  631.     }
  632.  
  633.     if (Sz1213 IN AdrModeB) {    /* Size in 12-13 (MOVEA) */
  634.         if (Dest.Mode == DReg)    /* Can't be to adata register! */
  635.         Error(DestLoc,ModeErr);    /* (Others are caught elsewhere). */
  636.         Op |= (Dest.Rn << 9);
  637.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  638.         if (Size == Word) Op |= 0x3000;
  639.         if (Size == Long) Op |= 0x2000;
  640.     }
  641.  
  642.     if (EA05a IN AdrModeB)        /* Effective address - all */
  643.         if ((Dest.Mode == DReg) || (Dest.Mode == ARDir))
  644.         EffAdr (&Src, ea);
  645.         else
  646.         Error (DestLoc, ModeErr);
  647.  
  648.     if (EA05b IN AdrModeB)    /* Eff. Addr. - all except ARDir */
  649.         if (Dest.Mode == DReg) {
  650.         EffAdr (&Src, dea);
  651.         Op |= (Dest.Rn << 9);
  652.         } else
  653.         Error (DestLoc, ModeErr);
  654.  
  655.     if (EA05c IN AdrModeB)        /* BTST */
  656.         if (Src.Mode == DReg)
  657.         EffAdr (&Dest, 0x0002);    /* All but ARDir */
  658.         else
  659.         EffAdr (&Dest, 0x0802);    /* All but ARDir/Imm */
  660.  
  661.     if(EA05d IN AdrModeB) {    /* All but PC relative & immediate */
  662.         EffAdr (&Dest, aea);
  663.         if ((Dest.Mode == ARDir) && (Size == Byte))
  664.         Error (OpLoc+5, SizeErr);
  665.     }
  666.  
  667.     if(EA05e IN AdrModeB) {    /* All but ARDir, PC relative, Imm */
  668.         if (Dest.Mode == Null)
  669.         EffAdr (&Src, (dea | aea));
  670.         else if (Src.Mode == Imm)
  671.         EffAdr (&Dest, (dea | aea));
  672.         else if (Src.Mode == DReg) {
  673.         if (AdrModeB == (Size67 | EA05e | Exten))
  674.             Error (SrcLoc, ModeErr);
  675.         EffAdr (&Dest, (dea | aea));
  676.         } else
  677.         Error (SrcLoc, ModeErr);
  678.     }
  679.  
  680.     if (EA05f IN AdrModeB) {    /* JMP, JSR, LEA, and PEA */
  681.         EffAdr (&Src, cea);
  682.         if (Rx911 IN AdrModeA)
  683.         if (Dest.Mode == ARDir)
  684.             Op |= (Dest.Rn << 9);   /* Address Reg. for LEA */
  685.         else
  686.             Error(DestLoc,ModeErr); /* Must load Address Reg. */
  687.         else
  688.         if (Dest.Mode != Null)
  689.             Error (DestLoc, OperErr);    /* No Dest. unless LEA */
  690.     }
  691.  
  692.     if (EA05x IN AdrModeB) {    /* AND and OR */
  693.         if (Dest.Mode == DReg)
  694.         EffAdr (&Src, dea);
  695.         else if (Src.Mode == DReg)
  696.         EffAdr (&Dest, mea | aea);
  697.         else
  698.         Error (SrcLoc, OperErr);
  699.     }
  700.  
  701.     if (EA05y IN AdrModeB) {    /* ADD and SUB */
  702.         if (Dest.Mode == DReg) {
  703.         EffAdr (&Src, ea);
  704.         if ((Src.Mode == ARDir) && (Size == Byte))
  705.             Error (OpLoc+4, SizeErr);
  706.         } else if (Src.Mode == DReg)
  707.         EffAdr (&Dest, (mea | aea));
  708.         else
  709.         Error (SrcLoc, ModeErr);
  710.     }
  711.     }
  712.  
  713.     if (EA05z IN AdrModeB) {        /* MOVEM */
  714.     if (Pass2) {
  715.         if (Src.Mode == MultiM) {        /* Move to memory. */
  716.         EffAdr (&Dest, (mea | aea | 0x0008));
  717.         ExtL = Src.Value;
  718.         i = (Dest.Mode == ARPre);    /* ExtL flip indicator */
  719.         } else if (Dest.Mode == MultiM) {    /* Move from memory. */
  720.         Op |= 0x0400;            /* Set direction. */
  721.         EffAdr (&Src, (mea | 0x0810));
  722.         ExtL = Dest.Value;
  723.         i = (Src.Mode == ARPre);
  724.         } else {
  725.         Error (SrcLoc, OperErr);
  726.         i = FALSE;
  727.         }
  728.         if (i) {                /* Flip ExtL if ARPre. */
  729.         j = 0;
  730.         for (i = 0; i < 8; i++)
  731.             j |= (ExtL & (1<<i)) << (15-i*2);
  732.         for (i = 8; i < 16; i++)
  733.             j |= (ExtL & (1<<i)) >> (i*2-15);
  734.         ExtL = j;
  735.         }
  736.     }
  737.     nO += 2;    /* Extension is part of OpCode. */
  738.     InstSize += 2;
  739.     }
  740.  
  741.     if (Pass2) {
  742.  
  743.     if (EA611 IN AdrModeB) {    /* Eff. Addr. in 6-11 (MOVE) */
  744.         if (Dest.Mode == CCR) {        /* MOVE to CCR */
  745.         Op = 0x44C0;
  746.         EffAdr (&Src, dea);
  747.         } else if (Dest.Mode == SR) {    /* MOVE to SR */
  748.         Op = 0x46C0;
  749.         EffAdr (&Src, dea);
  750.         } else if (Src.Mode    == SR) {    /* MOVE from SR */
  751.         Op = 0x40C0;
  752.         EffAdr (&Dest, dea | aea);
  753.         } else if (Dest.Mode == USP) {    /* MOVE to USP */
  754.         Op = 0x4E60;
  755.         if (Src.Mode == ARDir)
  756.             Op |= Src.Rn;
  757.         else
  758.             Error (SrcLoc, ModeErr);
  759.         } else if (Src.Mode == USP) {    /* MOVE from USP */
  760.         Op = 0x4E68;
  761.         if (Dest.Mode == ARDir)
  762.             Op |= Dest.Rn;
  763.         else
  764.             Error (DestLoc, ModeErr);
  765.         } else {            /* General MOVE instruction */
  766.         EffAdr (&Src, (ea | xxx));
  767.         if ((Size == Byte) && (Src.Mode == ARDir))
  768.             Error (SrcLoc, SizeErr);
  769.         if (Src.Mode > 12)
  770.             Error (SrcLoc, ModeErr);
  771.         if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12))
  772.             Error (DestLoc, ModeErr);
  773.         else if (Dest.Mode < 8)    /* Register direct or indirect */
  774.             Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn << 9);
  775.         else        /* Absolute, PC relative, or immediate */
  776.             Op |= 0x01C0 | ((Dest.Mode - 8) << 9);
  777.         OperExt (&Dest);        /* Set up extension word. */
  778.         }
  779.     }
  780.  
  781.     if ((Dest.Mode == CCR) && (Src.Mode == Imm)) {
  782.         if ((Size67 IN AdrModeB)
  783.         && (EA05e IN AdrModeB)
  784.         && (Exten IN AdrModeB))
  785.         if (0x0400 IN Op)    /* not ANDI/EORI/ORI */
  786.             Error (DestLoc, ModeErr);
  787.         else
  788.             Op = (Op & 0xFF00) | 0x003C;
  789.     }
  790.  
  791.     if ((Dest.Mode == SR) && (Src.Mode == Imm)) {
  792.         if ((Size67 IN AdrModeB)
  793.         && (EA05e IN AdrModeB)
  794.         && (Exten IN AdrModeB))
  795.         if (0x0400 IN Op)    /* not ANDI/EORI/ORI */
  796.             Error (DestLoc, ModeErr);
  797.         else
  798.             Op = (Op & 0xFF00) | 0x007C;
  799.     }
  800.     }
  801.  
  802.     ObjOp = Op;
  803.     InstSize += 2;
  804.     nO += 2;
  805.     if (nO > 2) {
  806.     templong = ExtL;            /* Add extension word. */
  807.     ObjOp = (ObjOp << 16) | (templong & 0x0000FFFFL);
  808.     }
  809.     if ((AdrModeA != 0) || (AdrModeB != 0)) {
  810.     InstSize += (nS = GetInstModeSize (Src.Mode));
  811.     ObjSrc = Src.Value;
  812.     if ((Src.Mode == Imm) && (Size == Byte))
  813.         ObjSrc &= 0xFF;    /* Pad a byte value with zeros. */
  814.     InstSize += (nD = GetInstModeSize (Dest.Mode));
  815.     ObjDest = Dest.Value;
  816.     }
  817.     if (quick) {
  818.     InstSize -= nS;        /* Source operand is in Op. */
  819.     nS = 0;
  820.     }
  821.  
  822.     if (Pass2) {
  823.     if ((nS!=0) && (Src.Hunk!=ABSHUNK)) {    /* SrcOp is relocatable. */
  824.         if ((Src.Mode == AbsL)
  825.         || (Src.Mode == AbsW)
  826.         || (Src.Mode == ARDisp)
  827.         || (Src.Mode == PCDisp)
  828.         || (Src.Mode == Imm)) {
  829.         templong = AddrCnt+nO;    /* 32- or 16-bit relocatable */
  830.         PutRel (templong, Src.Hunk, nS);
  831.         }
  832.         if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) {
  833.         templong = AddrCnt + nO + 1;    /* 8-bit relocatable */
  834.         PutRel (templong, Src.Hunk, 1);
  835.         }
  836.     }
  837.     if ((nD!=0) && (Dest.Hunk!=ABSHUNK)) {    /* DestOp is relocatable. */
  838.         if ((Dest.Mode == AbsL)
  839.         || (Dest.Mode == AbsW)
  840.         || (Dest.Mode == ARDisp)
  841.         || (Dest.Mode == PCDisp)
  842.         || (Dest.Mode == Imm)) {
  843.         templong = AddrCnt+nO+nS; /* 32- or 16-bit relocatable */
  844.         PutRel (templong, Dest.Hunk, nD);
  845.         }
  846.         if ((Dest.Mode==ARDisX) || (Dest.Mode==PCDisX)) {
  847.         templong = AddrCnt+nO+nS+1;    /* 8-bit relocatable */
  848.         PutRel (templong, Dest.Hunk, 1);
  849.         }
  850.     }
  851.     }
  852.     AddrAdv = InstSize;
  853. }
  854.  
  855.  
  856.  
  857. PackFwdBranch (dummy) int dummy;
  858. /* Drops expired entries (more than 128 bytes old)
  859.     from the forward branch optimization candidate table
  860.     and the label fixup table.                */
  861. {
  862.     register struct FwdBr *fp1, *fp2;
  863.     register struct SymTab **fsp, **fsp2, **fsp3;
  864.  
  865.     fp2 = FwdBranch;
  866.     while ((fp2 < FwdLim1) && (fp2->Loc < (AddrCnt - 128)))
  867.     fp2++;            /* Find the first unexpired entry. */
  868.  
  869.     if (fp2 > FwdBranch) {        /* If we can drop anything, */
  870.     fp1 = FwdBranch;        /*  shift active entries    */
  871.     while (fp2 < FwdLim1) {        /*  over expired ones.      */
  872.         fp1->Loc    = fp2->Loc;
  873.         fp1->FwdSym = fp2->FwdSym;
  874.         fp1->Line   = fp2->Line;
  875.         fp1++;
  876.         fp2++;
  877.     }
  878.     FwdLim1 = fp1;    /* The table now ends here. */
  879.     }
  880.  
  881.     if (FwdLim1 <= FwdBranch)
  882.     FwdFixLimit = FwdBranchFix;    /* No outstanding branches */
  883.  
  884.     for (fsp = FwdBranchFix; fsp < FwdFixLimit; fsp++) {
  885.     if ((*fsp)->Val < (AddrCnt - 128)) {
  886.         fsp2 = fsp3 = fsp;        /* Now drop expired label entries. */
  887.         fsp3++;
  888.         while (fsp3 < FwdFixLimit)
  889.         *fsp2++ = *fsp3++;
  890.         FwdFixLimit--;
  891.     }
  892.     }
  893. }
  894.